package com.alinesno.cloud.common.facade.wrapper;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.domain.Specification;

import com.fasterxml.jackson.annotation.JsonProperty;


public class RestWrapper extends Wrapper {

	private static final long serialVersionUID = 2286891850011652336L;

	private static final Logger log = LoggerFactory.getLogger(RestWrapper.class);
	
	@JsonProperty
	private List<Condition> condition = new ArrayList<Condition>();

	public RestWrapper eq(String column, Object params) {

		log.debug("column = {} , params = {}", column, params);
		
		condition.add(new Condition(column, params));
		return this;
	}

	public List<Condition> getCondition() {
		return condition;
	}

	public RestWrapper setCondition(List<Condition> condition) {
		this.condition = condition;
		return this;
	}

	public RestWrapper where(String sqlWhere, Object... params) {
		
		return null;
	}

	public RestWrapper ne(String column, Object params) {
		
		return null;
	}

	public RestWrapper allEq(Map<String, Object> params) {
		if(params != null) {
			for(String k : params.keySet()) {
				condition.add(new Condition(k, params.get(k)));
			}
		}
		return this ;
	}

	public RestWrapper gt(String column, Object params) {
		
		return null;
	}

	public RestWrapper ge(String column, Object params) {
		
		return null;
	}

	public RestWrapper lt(String column, Object params) {
		condition.add(new Condition("lt" , column, params));
		return this ;
	}

	public RestWrapper le(String column, Object params) {
		
		return null;
	}

	public RestWrapper and(String sqlAnd, Object... params) {
		
		return null;
	}

	public RestWrapper andNew() {
		
		return null;
	}

	public RestWrapper andNew(String sqlAnd, Object... params) {
		
		return null;
	}

	public RestWrapper and(String column, String params) {
		
		return null;
	}

	public RestWrapper or(String column, String params) {
		
		return null;
	}

	public RestWrapper or(boolean condition, String sqlOr, Object... params) {
		
		return null;
	}

	public RestWrapper or(String sqlOr, Object... params) {
		
		return null;
	}

	public RestWrapper orNew() {
		
		return null;
	}

	public RestWrapper orNew(String sqlOr, Object... params) {
		
		return null;
	}

	public RestWrapper groupBy(String columns) {
		
		return null;
	}

	public RestWrapper having(String sqlHaving, Object... params) {
		
		return null;
	}

	public RestWrapper orderBy(String columns) {
		
		return null;
	}

	public RestWrapper orderBy(String columns, boolean isAsc) {
		
		return null;
	}

	public RestWrapper like(String column, String value) {
		
		return null;
	}

	public RestWrapper notLike(String column, String value) {
		
		return null;
	}

	public RestWrapper like(String column, String value, String type) {
		
		return null;
	}

	public RestWrapper notLike(String column, String value, String type) {
		
		return null;
	}

	public RestWrapper isNotNull(String columns) {
		
		return null;
	}

	public RestWrapper isNull(String columns) {
		
		return null;
	}

	public RestWrapper exists(String value) {
		
		return null;
	}

	public RestWrapper notExists(String value) {
		
		return null;
	}

	public RestWrapper in(String column, String value) {
		
		return null;
	}

	public RestWrapper notIn(String column, String value) {
		
		return null;
	}

	public RestWrapper in(String column, Collection<?> value) {
		
		return null;
	}

	public RestWrapper notIn(String column, Collection<?> value) {
		
		return null;
	}

	public RestWrapper in(String column, Object[] value) {
		
		return null;
	}

	public RestWrapper notIn(String column, Object... value) {
		
		return null;
	}

	public RestWrapper between(String column, Object val1, Object val2) {
		
		return null;
	}

	public RestWrapper notBetween(String column, Object val1, Object val2) {
		
		return null;
	}

	public <T> Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {

		List<Predicate> predicates = new ArrayList<Predicate>();

		if (condition != null && condition.size() > 0) {
			for (Condition c : condition) {

				String conditionKey = c.getCondition();
				String column = c.getColumn();
				Object params = c.getParams();

				switch (conditionKey) {
					case "eq": predicates.add(criteriaBuilder.equal(root.get(column),params)); break;
					case "like": predicates.add(criteriaBuilder.like(root.get(column), "%" + params + "%")); break;
					case "notLike": predicates.add(criteriaBuilder.notLike(root.get(column), "%" + params + "%")); break;
					case "likeLeft": predicates.add(criteriaBuilder.like(root.get(column), "%" + params)); break;
					case "likeRight": predicates.add(criteriaBuilder.like(root.get(column), params + "%")); break;
					case "le": predicates.add(criteriaBuilder.le(root.get(column), Double.parseDouble(params + ""))); break;
					case "lt": predicates.add(criteriaBuilder.lt(root.get(column), Double.parseDouble(params + ""))); break;
					case "ge": predicates.add(criteriaBuilder.ge(root.get(column), Double.parseDouble(params + ""))); break;
					case "gt": predicates.add(criteriaBuilder.gt(root.get(column), Double.parseDouble(params + ""))); break;
					default: predicates.add(criteriaBuilder.equal(root.<Object>get(column), params)); break;
				}
			}
		}

		return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
	}
	
	@SuppressWarnings("serial")
	public <T> Specification<T> toSpecification(){
		
		Specification<T> spec = new Specification<T>() {
			@Override
			public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
				return this.toPredicate(root, query, criteriaBuilder) ; 
			}
		} ; 
		
		return spec ; 
	}

	/**
	 * 条件转换
	 * @param c 前端传递参数  
	 */
	public void builderCondition(Map<String, Object> c) {
		if(c != null) {
			if (condition != null) {
				Iterator<Map.Entry<String, Object>> iterator = c.entrySet().iterator();
				
				while (iterator.hasNext()) {
					Map.Entry<String, Object> me = iterator.next();
					String[] keys = me.getKey().trim().split("\\|");
					Object value = me.getValue();

					log.debug("key = {} , value = {}", keys[0], value);
					
					if(StringUtils.isBlank(keys[0]) || value == null || StringUtils.isBlank(""+value)) {
						continue ;
					}
					
					Condition condition = new Condition() ; 
					
					if (keys.length == 1) { // 条件 
						
						condition.setCondition("eq"); 
						condition.setColumn(keys[0]); 
						condition.setParams(String.valueOf(me.getValue()));
						
					} else if (keys.length >= 2) {  // 日期 
						
						condition.setCondition(keys[1]); 
						condition.setColumn(keys[0]); 
						condition.setParams(String.valueOf(me.getValue()));
					}
					
					this.condition.add(condition) ; 
				}
			}
		}
	}
	
}
